﻿using System.Collections.Generic;
using AzureGames.Domain.Services;
using AzureGames.Model.Statistics;
using InMemory = AzureGames.Data.InMemory;
using AzureGames.Domain.Handlers;
using Model = AzureGames.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using AzureGames.Data;
using System.Threading;
using AzureGames.Domain.Models;
using System.Linq;
using AzureGames.Domain.Tests.Helper;
using AzureGames.Model;

namespace AzureGames.Domain.Tests
{
    /// <summary>
    ///This is a test class for GetGameDefinitionTest and is intended
    ///to contain all GetGameDefinitionTest Unit Tests
    ///</summary>
    [TestClass()]
    public class GameDetailsTests
    {
        private static string[] playerIDs = new string[]
                                              {
                                                 new Guid("DF2AA2FD-6AA8-474F-B29B-BCCD8247D397").ToString(),
                                                  new Guid("2F851A61-249B-4942-9FE4-2276D39183EF").ToString(),
                                                  new Guid("328C8086-B7FB-4F65-A0E2-6F2AE40E1300").ToString()
                                              };

        [TestMethod()]
        public void GameDetailsTest()
        {
            // create in memory repositories
            IBoardRepository boardRepository = new InMemory.BoardRepository();
            IGameDefinitionRepository gameDefinitionRepository = new InMemory.GameDefinitionRepository();
            INotificationRepository notificationRepository = new InMemory.NotificationRepository();
            IUserRepository userRepository = new InMemory.UserRepository();
            IUserStatisticsRepository userstatisticsRepository = new InMemory.StatisticsRepository();
            IGameStatisticsRepository gamestatisticsRepository = new InMemory.StatisticsRepository();
            IPlayerRepository playerRepository = new InMemory.PlayerRepository();
            NotificationService.Instance.IntializeNotificationService(notificationRepository, boardRepository);

            var gameDefinition = gameDefinitionRepository.GetGameDefinition(1);
            GetGameDetails getGameDetails = new GetGameDetails(gameDefinitionRepository, userstatisticsRepository, gamestatisticsRepository);
            RegisterNewGame registerNewGame = new RegisterNewGame(boardRepository, gameDefinitionRepository, notificationRepository, playerRepository, userstatisticsRepository, gamestatisticsRepository);
            UpdateBoard updateGameBoard = new UpdateBoard(gameDefinitionRepository, boardRepository, userstatisticsRepository, gamestatisticsRepository, playerRepository, notificationRepository);
            GetBoard getBoard = new GetBoard(boardRepository);


            var gameDetails = getGameDetails.Execute(1, playerIDs[0]);

            Assert.AreEqual(gameDetails.ID, gameDefinition.ID);
            Assert.AreEqual(gameDetails.Description, gameDefinition.Description);
            Assert.AreEqual(gameDetails.ShortDescription, gameDefinition.ShortDescription);
            Assert.AreEqual(gameDetails.Name, "Amazons");
            Assert.IsFalse(gameDetails.UserCreatedStatistics.ContainsKey(DateTime.Now.Date.ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.UserCompletedStatistics.ContainsKey(DateTime.Now.Date.ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.UserCancelledStatistics.ContainsKey(DateTime.Now.Date.ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.GameCancelledStatistics.ContainsKey(DateTime.Now.Date.ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.GameCompletedStatistics.ContainsKey(DateTime.Now.Date.ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.GameCreatedStatistics.ContainsKey(DateTime.Now.Date.ToString("yyyy-MM-dd")));

            var board1 = registerNewGame.Execute(1, playerIDs[0]);
            var board2 = registerNewGame.Execute(1, playerIDs[1]);
            var board3 = registerNewGame.Execute(1, playerIDs[0]);
            var board4 = registerNewGame.Execute(1, playerIDs[2]);
            var board5 = registerNewGame.Execute(1, playerIDs[1]);
            var board6 = registerNewGame.Execute(1, playerIDs[2]);

            // cancel two
            var boardModel = getBoard.Execute(board6.ID);
            boardModel.State = Board.Cancelled;
            updateGameBoard.Execute(boardModel);
            
            boardModel = getBoard.Execute(board5.ID);
            boardModel.State = Board.Cancelled;
            updateGameBoard.Execute(boardModel);

            // complete one
            boardModel = getBoard.Execute(board1.ID);
            boardModel.State = Board.Completed;
            updateGameBoard.Execute(boardModel);

            // add some older activity within time period
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-3).Date, Board.Completed);
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-3).Date, Board.Completed);
            gamestatisticsRepository.AddGameStatistic(1, GameType.MultiplePlayer, DateTime.Now.AddDays(-5).Date, Board.Cancelled);
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-4).Date, Board.Created);

            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-3).Date, playerIDs[0], Board.Completed);
            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-3).Date, playerIDs[0], Board.Completed);
            userstatisticsRepository.AddUserStatistic(1, GameType.MultiplePlayer, DateTime.Now.AddDays(-5).Date, playerIDs[0], Board.Cancelled);
            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-4).Date, playerIDs[0], Board.Created);

            // add some older activity outside time period
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-13).Date, Board.Completed);
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-13).Date, Board.Completed);
            gamestatisticsRepository.AddGameStatistic(1, GameType.MultiplePlayer, DateTime.Now.AddDays(-15).Date, Board.Cancelled);
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-14).Date, Board.Created);

            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-13).Date, playerIDs[0], Board.Completed);
            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-13).Date, playerIDs[0], Board.Completed);
            userstatisticsRepository.AddUserStatistic(1, GameType.MultiplePlayer, DateTime.Now.AddDays(-15).Date, playerIDs[0], Board.Cancelled);
            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-14).Date, playerIDs[0], Board.Created);


            // add some older activity for another user
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-2).Date, Board.Completed);
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-2).Date, Board.Completed);
            gamestatisticsRepository.AddGameStatistic(1, GameType.MultiplePlayer, DateTime.Now.AddDays(-6).Date, Board.Cancelled);
            gamestatisticsRepository.AddGameStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-5).Date, Board.Created);

            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-2).Date, playerIDs[1], Board.Completed);
            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-2).Date, playerIDs[1], Board.Completed);
            userstatisticsRepository.AddUserStatistic(1, GameType.MultiplePlayer, DateTime.Now.AddDays(-6).Date, playerIDs[1], Board.Cancelled);
            userstatisticsRepository.AddUserStatistic(1, GameType.SinglePlayer, DateTime.Now.AddDays(-5).Date, playerIDs[1], Board.Created);

            gameDetails = getGameDetails.Execute(1, playerIDs[0]);

            Assert.AreEqual(gameDetails.ID, gameDefinition.ID);
            Assert.AreEqual(gameDetails.Description, gameDefinition.Description);
            Assert.AreEqual(gameDetails.ShortDescription, gameDefinition.ShortDescription);
            Assert.AreEqual(gameDetails.Name, "Amazons");
            // two games for player
            Assert.AreEqual(gameDetails.UserCreatedStatistics[DateTime.Now.Date.ToString("yyyy-MM-dd")], 2);
            Assert.AreEqual(gameDetails.UserCompletedStatistics[DateTime.Now.Date.ToString("yyyy-MM-dd")], 0);
            Assert.AreEqual(gameDetails.UserCancelledStatistics[DateTime.Now.Date.ToString("yyyy-MM-dd")], 0);
            Assert.AreEqual(gameDetails.GameCancelledStatistics[DateTime.Now.Date.ToString("yyyy-MM-dd")], 0);
            Assert.AreEqual(gameDetails.GameCompletedStatistics[DateTime.Now.Date.ToString("yyyy-MM-dd")], 0);
            // three games total
            Assert.AreEqual(gameDetails.GameCreatedStatistics[DateTime.Now.Date.ToString("yyyy-MM-dd")], 3);

            Assert.IsFalse(gameDetails.UserCreatedStatistics.ContainsKey(DateTime.Now.Date.AddDays(-1).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.UserCompletedStatistics.ContainsKey(DateTime.Now.Date.AddDays(-1).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.UserCancelledStatistics.ContainsKey(DateTime.Now.Date.AddDays(-1).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.GameCancelledStatistics.ContainsKey(DateTime.Now.Date.AddDays(-1).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.GameCompletedStatistics.ContainsKey(DateTime.Now.Date.AddDays(-1).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.GameCreatedStatistics.ContainsKey(DateTime.Now.Date.AddDays(-1).ToString("yyyy-MM-dd")));

            // user does not have activity on this day
            Assert.IsFalse(gameDetails.UserCreatedStatistics.ContainsKey(DateTime.Now.Date.AddDays(-2).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.UserCompletedStatistics.ContainsKey(DateTime.Now.Date.AddDays(-2).ToString("yyyy-MM-dd")));
            Assert.IsFalse(gameDetails.UserCancelledStatistics.ContainsKey(DateTime.Now.Date.AddDays(-2).ToString("yyyy-MM-dd")));
            // but the game has for other players
            Assert.AreEqual(gameDetails.GameCancelledStatistics[DateTime.Now.Date.AddDays(-2).ToString("yyyy-MM-dd")], 0);
            Assert.AreEqual(gameDetails.GameCompletedStatistics[DateTime.Now.Date.AddDays(-2).ToString("yyyy-MM-dd")], 1);
            Assert.AreEqual(gameDetails.GameCreatedStatistics[DateTime.Now.Date.AddDays(-2).ToString("yyyy-MM-dd")], 1);

            Assert.AreEqual(gameDetails.UserCreatedStatistics[DateTime.Now.Date.AddDays(-3).ToString("yyyy-MM-dd")], 1);
            Assert.AreEqual(gameDetails.UserCompletedStatistics[DateTime.Now.Date.AddDays(-3).ToString("yyyy-MM-dd")], 1);
            Assert.AreEqual(gameDetails.UserCancelledStatistics[DateTime.Now.Date.AddDays(-3).ToString("yyyy-MM-dd")], 0);
            Assert.AreEqual(gameDetails.GameCancelledStatistics[DateTime.Now.Date.AddDays(-3).ToString("yyyy-MM-dd")], 0);
            Assert.AreEqual(gameDetails.GameCompletedStatistics[DateTime.Now.Date.AddDays(-3).ToString("yyyy-MM-dd")], 1);
            Assert.AreEqual(gameDetails.GameCreatedStatistics[DateTime.Now.Date.AddDays(-3).ToString("yyyy-MM-dd")], 1);

        }
    }
}